package com.wfm.files;

import java.io.*;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class MultiThreadedFileProcessor {
    private static final int THREAD_COUNT = 5;
    private static final int LINES_PER_THREAD = 1;

    public static void main(String[] args) throws IOException, InterruptedException {
        String fileAPath = "input.txt"; // 输入文件
        String fileBPath = "output.txt"; // 输出文件

        // 读取文件A的内容并记录每行的起始位置和长度
        List<LineInfo> lineInfos = new ArrayList<>();
        try (BufferedReader reader = new BufferedReader(new FileReader(fileAPath))) {
            String line;
            long position = 0;
            while ((line = reader.readLine()) != null) {
                lineInfos.add(new LineInfo(position, line.length()));
                position += line.length() + 1; // +1 for the newline character
            }
        }

        // 创建线程池
        ExecutorService executor = Executors.newFixedThreadPool(THREAD_COUNT);

        try (RandomAccessFile file = new RandomAccessFile(fileAPath, "rw");
             FileChannel channel = file.getChannel()) {

            int totalLines = lineInfos.size();
            for (int i = 0; i < totalLines; i += LINES_PER_THREAD) {
                final int start = i;
                final int end = Math.min(i + LINES_PER_THREAD, totalLines);
                executor.submit(() -> {
                    try {
                        writeLinesToFileB(channel,fileBPath, lineInfos.subList(start, end));
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                });
            }

        }
        executor.shutdown();
        executor.awaitTermination(Long.MAX_VALUE, java.util.concurrent.TimeUnit.NANOSECONDS);
    }

    private static void writeLinesToFileB(FileChannel src,String fileBPath, List<LineInfo> lines) throws IOException {
        try (RandomAccessFile file = new RandomAccessFile(fileBPath, "rw");
             FileChannel channel = file.getChannel()) {
            // 计算总长度
            long totalSize = lines.stream().mapToLong(line -> line.length).sum();
            MappedByteBuffer bufferSrc = src.map(FileChannel.MapMode.READ_ONLY, lines.get(0).position, totalSize);
            MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_WRITE, lines.get(0).position, totalSize);

            buffer.put(bufferSrc);
            for (LineInfo lineInfo : lines) {
                buffer.position((int) lineInfo.position);
                buffer.put(lineInfo.line.getBytes());
                buffer.put((byte) '\n'); // 写入换行符
            }
            buffer.force(); // 确保写入磁盘
        }
    }

    static class LineInfo {
        long position; // 行的起始位置
        int length; // 行的长度
        String line; // 行的内容

        LineInfo(long position, int length) {
            this.position = position;
            this.length = length;
        }
    }
}